package ongd.negocio.sesion;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import ongd.negocio.gestion.ControladorSocio;
import ongd.negocio.gestion.Cuota;
import ongd.servicios.persistencia.exceptions.IllegalOrphanException;
import ongd.servicios.persistencia.exceptions.NonexistentEntityException;
import ongd.servicios.persistencia.exceptions.PreexistingEntityException;

/**
 * Clase que ejecuta las tareas automáticas programadas para la apliación.
 *
 * @author <a href="mailto:egi0002@alu.ubu.es">Elena García Iglesias</a>
 * @author <a href="mailto:cms0021@alu.ubu.es">Cristina Martínez Sanz</a>
 * @version 1.0 20120124
 *
 */
public class TareasAutomaticas {
    /**
     * Objeto del tipo controladorSesion
     */
    private ControladorSesion controladorSesion;
    
    /**
     * Objeto del tipo tareasAutomaticas
     */
    private static TareasAutomaticas tareas;
    
    /**
     * Método que establecerá una única instancia para la tarea.
     * @return tareas
     */
    public static synchronized TareasAutomaticas obtenerInstancia(){
        if (tareas==null){
            tareas = new TareasAutomaticas();
        }
        return tareas;
    }
    
    /**
     * Constructor de la clase.
     */
    private TareasAutomaticas(){
        controladorSesion = new ControladorSesion(false);
        controladorSesion.conectarBD(false);
        Thread hilo = new Thread(new Hilo());
        hilo.start();
    }
    
    /**
     * Clase interna que creará los hilos para realizar las tareas automáticas.
     */
    class Hilo implements Runnable{    
        /**
         * Metodo que arranca los hilos.
         */
        @Override
        public void run() {
            while (true){
                try {
                    generarNuevasCuotas();
                    generarEmailCuotas();
                    Thread.currentThread().sleep(12*60*60*1000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
        /**
         * Método que genera las cuotas automaticamente.
         */
        private void generarNuevasCuotas(){
            try {
                controladorSesion.getControladorSocio().generarCuotasAutomaticas();
            } catch (PreexistingEntityException ex) {
                Logger.getLogger(TareasAutomaticas.class.getName()).log(Level.SEVERE, null, ex);
            } catch (Exception ex) {
                Logger.getLogger(TareasAutomaticas.class.getName()).log(Level.SEVERE, null, ex);
            }
        }  
        
        /**
         * Método que genera emails con las cuotas que llegan a su vencimiento. 
         */
        private void generarEmailCuotas(){ 
            Calendar fechaMin= Calendar.getInstance();
            Calendar fechaMax= Calendar.getInstance();
            int mes= Integer.parseInt(new SimpleDateFormat("MM").format(new Date()));
            int annio=Integer.parseInt(new SimpleDateFormat("yyyy").format(new Date()));
            ControladorSocio contSocio= controladorSesion.getControladorSocio();            
            mes -=2;
            if(mes==-1){
                mes=11;
                annio -=1;
            }
            fechaMin.set(Calendar.DAY_OF_MONTH, 28);
            fechaMin.set(Calendar.MONTH, mes);
            fechaMin.set(Calendar.YEAR, annio);
            
            mes= Integer.parseInt(new SimpleDateFormat("MM").format(new Date()));
            annio=Integer.parseInt(new SimpleDateFormat("yyyy").format(new Date()));
            if(mes==12){
                mes=0;
                annio +=1;
            }
            fechaMax.set(Calendar.DAY_OF_MONTH, 1);
            fechaMax.set(Calendar.MONTH, mes);
            fechaMax.set(Calendar.YEAR, annio);
            //Obtenemos la lista de cuotas que estan entre esas dos fechas y no tienen alertas.
            List<Cuota> cuotasSinalertas = new ArrayList<Cuota>();
            cuotasSinalertas=contSocio.obtenerCuotasSinAlertas(fechaMin.getTime(), fechaMax.getTime());
            
            //LLamamos al metodo que crea el email si existen cuotas
            if(!cuotasSinalertas.isEmpty()){
                List<Cuota> cuotasPendientes= new ArrayList<Cuota>();
                cuotasPendientes= contSocio.obtenerCuotasPendientesAvisadas(fechaMin.getTime());
                if(controladorSesion.getControladorUsuario().enviarEmailCuotasSinAlertas(cuotasSinalertas, cuotasPendientes)){
                    try {
                        contSocio.establecerCuotasConAlertas(cuotasSinalertas);
                    } catch (IllegalOrphanException ex) {
                        Logger.getLogger(TareasAutomaticas.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (NonexistentEntityException ex) {
                        Logger.getLogger(TareasAutomaticas.class.getName()).log(Level.SEVERE, null, ex);
                    } catch (Exception ex) {
                        Logger.getLogger(TareasAutomaticas.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
            }
        }
    }

    /**
     * Método que devuelve el controlador de la sesion.
     * @return controladorSesion
     * @see #setControladorSesion
     */
    public ControladorSesion getControladorSesion() {
        return controladorSesion;
    }

    /**
     * Método que devuelve las tareas automáticas que se van a realizar.
     * @return tareas
     * @see #setTareas
     */
    public static TareasAutomaticas getTareas() {
        return tareas;
    }

    /**
     * Método que asigna un nuevo valor al controlador de sesión.
     * @param controladorSesion Nuevo valor de la variable
     * @see #getControladorSesion
     */
    public void setControladorSesion(ControladorSesion controladorSesion) {
        this.controladorSesion = controladorSesion;
    }

    /**
     * Método que asigna unas nuevas tareas automáticas.
     * @param tareas Nuevo valor de la variable
     * @see #getTareas
     */
    public static void setTareas(TareasAutomaticas tareas) {
        TareasAutomaticas.tareas = tareas;
    }
    
    
}

